//
//  UDPListener.swift
//  swifttest1
//
//  Created by kologe on 2024/9/16.
//

import Foundation
import Network


class UDPListener{
    var listener:NWListener
    var getPort:Bool = true
    
    
    init(port: UInt16) {
        let nwEndpoint = NWEndpoint.Port(rawValue: port)!
        let nwParameters = NWParameters.udp
        nwParameters.allowLocalEndpointReuse = true
        self.listener = try! NWListener(using: nwParameters, on: nwEndpoint)
    }
    
    func prepare(port: UInt16){
        if self.listener.state == .cancelled{
            let nwEndpoint = NWEndpoint.Port(rawValue: port)!
            let nwParameters = NWParameters.udp
            nwParameters.allowLocalEndpointReuse = true
            self.listener = try! NWListener(using: nwParameters, on: nwEndpoint)
        }
    }
    
    func start() {
        listener.stateUpdateHandler = { [self] newState in
            switch newState {
            case .ready:
                print("udp Server is ready and listening on port \(self.listener.port!)")
                if(getPort == false){
                    //跳出弹窗提示用户，可以开始scan
                    getPort = true
                }
            case .failed(let error):
                error_log("udp Server failed with error: \(error)")
                if error.errorCode == 48{
                    //跳出弹窗提示用户，等一会在重新scan
                    getPort = false
                }
            default:
                break
            }
        }
        
        listener.newConnectionHandler = { newConnection in
            self.handleNewConnection(newConnection)
        }
        
        listener.start(queue: .global())
    }
    
    func handleNewConnection(_ connection: NWConnection) {
        connection.stateUpdateHandler = { newState in
            switch newState {
            case .ready:
                print("udp New client connected")
                self.receiveData(from: connection)
            case .failed(let error):
                error_log("Connection failed with error: \(error)")
                connection.cancel()
            case .cancelled:
                print("Connection cancelled")
            default:
                break
            }
        }
        
        connection.start(queue: .global())
    }
    
    func receiveData(from connection: NWConnection) {
        connection.receiveMessage { data, context, isComplete, error in
            if let data = data, !data.isEmpty {
                info_log("udp Received data: \(String(data: data, encoding: .utf8) ?? "")")
                if let remoteScan:Scan = Scan.deCodeFromJson(jsonData: data){
                    
                    let localIp = NetMessage.shared().getIPAddress()
                    //                //本机的发送的请求就不用回应了
                    //                if localIp == remoteScan.ip{
                    //                    return
                    //                }
                    //回应请求，发送自己的信息。
                    if(remoteScan.protocolType == SCAN_MESSAGE_REQ){
                        Scan.receive_req(remoteScan: remoteScan)
                    }else if(remoteScan.protocolType == SCAN_MESSAGE_ANS){
                        //收到回应，增加结果
                        Scan.receive_ans(remoteScan: remoteScan)
                    }
                }
            }
            if isComplete {
                print("Connection closed by client")
                connection.cancel()
            } else if let error = error {
                error_log("Failed to receive data: \(error)")
                connection.cancel()
            } else {
                self.receiveData(from: connection)
            }
        }
    }
    
    func close(){
        #if DEBUG
        print("UDP Listener cancel")
        #endif
        listener.cancel()
    }
}
